#include <stdlib.h>

#include "Error.h"
#include "Icon.h"
#include "WimpSWIs.h"

#include "appdata.h"
#include "control.h"
#include "log.h"
#include "msgtrandyn.h"

app_data *app_data_new(void)
{
  int current = -1;
  int next = -1;
  int freepool = -1;
  int i;
  app_data *app = malloc(sizeof(app_data));

  if (!app)
  {
    Error_Report(0, MSG_NOMEM);
    return NULL;
  }

  app->win = 0;

  app->background_help = NULL;
  app->draggable_help = NULL;
  for (i = 0; i < icon_NumIcons; ++i)
  {
    app->icon_help[i] = NULL;
  }

  /*
  app->handlers.drag_in = FALSE;
  app->handlers.drag_out = FALSE;
  app->handlers.click_next = FALSE;
  */

  app->datasave_ref = 0;

  app->disc_slider = app->total_slider = NULL;

  app->next_handler = app->back_handler = NULL;

  Error_CheckFatal(Wimp_SlotSize(&current, &next, &freepool));
  LOG("freepool = %d (%dK), next = %d (%dK)\n",
      freepool, freepool / 1024, next, next / 1024);
  freepool -= next;
  LOG("Free memory = %d (%dK)\n", freepool, freepool / 1024);
  if (freepool < 8192 * 1024)
  {
    LOG("Using bunzip2's low memory option\n");
    app->lowmem = TRUE;
  }
  else
  {
    LOG("Not using bunzip2's low memory option\n");
    app->lowmem = FALSE;
  }

  return app;
}

void app_data_show_message(const app_data *app, const char *message)
{
  Icon_SetText(app->win, icon_Message, (char *) message);
}

void app_data_blank_message(const app_data *app)
{
  Icon_SetText(app->win, icon_Message, NULL);
}

void app_data_set_filename_text(const app_data *app, const char *text)
{
  Icon_SetText(app->win, icon_Filename, (char *) text);
}

void app_data_filename_writable(const app_data *app, BOOL writable)
{
  icon_flags flags;

  Icon_AlterValidation(app->win, icon_Filename,
                       (char *) (writable ? "Pptr_write;Kta" : "R2"));
  Icon_SetBackColour(app->win, icon_Filename,
                     writable ? colour_WHITE : colour_GREY1);
  flags.value = 0;
  flags.data.buttontype = writable ? iconbtype_WRITABLE : iconbtype_NEVER;
  Wimp_SetIconState(app->win, icon_Filename, flags.value, 0xf000);
}

void app_data_lookup_help(app_data *app)
{
  int i;

  app->background_help = MsgTransDyn_Lookup(messages, "HelpBackground", FALSE);

  for (i = 0; i < icon_NumIcons; ++i)
  {
    app->icon_help[i] = MsgTransDyn_Lookup(messages,
                                           control_splice_token("Help", i),
                                           FALSE);
  }

  app->draggable_help = app->icon_help[icon_Draggable];
  app->message_help = app->icon_help[icon_Message];
}

void app_data_toggle_draggable(app_data *app, BOOL draggable)
{
  icon_flags flags;

  flags.value = 0;
  flags.data.buttontype = draggable ? iconbtype_CLICKDRAG : iconbtype_NEVER;
  Wimp_SetIconState(app->win, icon_Filename, flags.value, 0xf000);
  app->icon_help[icon_Draggable] = draggable ? app->draggable_help : NULL;
}

void app_data_toggle_message_help(app_data *app, BOOL show)
{
  app->icon_help[icon_Message] = show ? app->message_help : NULL;
}

void app_data_shade_next(app_data *app, BOOL shade)
{
  Icon_SetShade(app->win, icon_Next, shade);
}

void app_data_shade_back(app_data *app, BOOL shade)
{
  Icon_SetShade(app->win, icon_Back, shade);
}

void app_data_set_draggable_icon(app_data *app, const char *sprite_name)
{
  Icon_SetText(app->win, icon_Draggable, (char *) sprite_name);
}

static slider_info *app_data_slider_new(window_handle win, icon_handle icon)
{
  slider_info *slider = malloc(sizeof(slider_info));

  if (!slider)
  {
    Error_Report(0, MSG_NOMEM);
    return NULL;
  }

  slider->window = win;
  slider->icon = icon;
  slider->value = 0;
  slider->limits.min = 0;
  slider->limits.max = 10;     /* Arbitrary */
  slider->colour.background = colour_GREY1;
  slider->colour.foreground = colour_DARK_BLUE;
  slider->border.x = slider->border.y = 12;
  slider->knob.spritearea = NULL;
  slider->knob.sprite = NULL;
  slider->flags.vertical = 0;
  slider->flags.rgb = 0;
  slider->flags.dragging = 0;
  slider->flags.clickstop = 0;
  slider->flags.reserved = 0;
  slider->update = NULL;
  slider->reference = NULL;

  return slider;
}

BOOL app_data_create_sliders(app_data *app)
{
  app->disc_slider = app_data_slider_new(app->win, icon_Slider1);
  app->total_slider = app_data_slider_new(app->win, icon_Slider2);

  return (app->disc_slider && app->total_slider);
}

void app_data_show_item_status(app_data *app, const char *token,
                               const char *item_name)
{
  char *msg = MsgTransDyn_LookupPS(messages, token, item_name,
                                   NULL, NULL, NULL, FALSE);

  app_data_set_filename_text(app, msg ? msg : item_name);
  free(msg);
}

void app_data_set_next_handler(app_data *app, event_handler handler)
{
  LOG("Registering Next handler %p\n", handler);
  if (app->next_handler)
  {
    LOG("Replacing old Next handler %p\n", app->next_handler);
    Event_Release(event_CLICK, app->win, icon_Next, app->next_handler, app);
  }
  Event_Claim(event_CLICK, app->win, icon_Next, handler, app);
  app->next_handler = handler;
}

void app_data_set_back_handler(app_data *app, event_handler handler)
{
  LOG("Registering Back handler %p\n", handler);
  if (app->back_handler)
  {
    LOG("Replacing old Back handler %p\n", app->back_handler);
    Event_Release(event_CLICK, app->win, icon_Back, app->back_handler, app);
  }
  Event_Claim(event_CLICK, app->win, icon_Back, handler, app);
  app->back_handler = handler;
}

void app_data_release_handlers(app_data *app)
{
  LOG("Releasing Back/Next handlers: ");
  if (app->next_handler)
  {
    LOGQ("Next %p ", app->next_handler);
    Event_Release(event_CLICK, app->win, icon_Next, app->next_handler, app);
    app->next_handler = NULL;
  }
  if (app->back_handler)
  {
    LOGQ("Back %p", app->back_handler);
    Event_Release(event_CLICK, app->win, icon_Back, app->back_handler, app);
    app->back_handler = NULL;
  }
  LOGQ("\n");
}

